package com.wkq.util

/**
 *
 *@Author: wkq
 *
 *@Time: 2025/8/1 16:29
 *
 *@Desc:
 */
import android.content.Context
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.Signature
import android.os.Build
import android.util.Log
import java.security.MessageDigest
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
import java.util.Date

import android.util.Base64

object SignatureChecker {
    /**
    * 签名文件校验
     */
    fun isSignatureTampered(context: Context,shar265:String?,publicKey:String?,cn: String?): Boolean {
        return try {
            val packageInfo = getPackageInfo(context)

            val signatures = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                packageInfo.signingInfo?.apkContentsSigners
            } else {
                @Suppress("DEPRECATION")
                packageInfo.signatures
            }?: return true // 无签名，视为篡改

            // 校验每个签名（多签名场景）
            for (signature in signatures) {
                // 1. 校验签名哈希
                val signSha256 = getSignatureSha256(signature)
                if (signSha256 != shar265) {
                    return true
                }

                // 2. 校验证书公钥
                val key = getPublicKeyFromSignature(signature)
                if (key != publicKey) {
                    return true
                }

                // 3. 校验证书其他信息（如颁发者、有效期）
                val cert = getX509Certificate(signature)
                if (cert.issuerDN.name != cn || cert.notAfter.before(Date())) {
                    return true
                }
            }
            false // 所有校验通过，未篡改
        } catch (e: Exception) {
            true // 异常情况视为篡改（可能被Hook）
        }
    }


    private const val TAG = "PublicKeyExtractor"

    /**
     * 提取当前应用签名的公钥（Base64编码字符串）
     * @param context 上下文
     * @return 公钥字符串（可作为LEGAL_PUBLIC_KEY的值），失败返回null
     */
    fun extractPublicKey(context: Context): String? {
        return try {
            val packageManager = context.packageManager
            // 获取当前应用的签名信息
            val packageInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                // Android 9+ 使用新 API
                packageManager.getPackageInfo(
                    context.packageName,
                    PackageManager.GET_SIGNING_CERTIFICATES
                )
            } else {
                // 低版本使用旧 API
                @Suppress("DEPRECATION")
                packageManager.getPackageInfo(
                    context.packageName,
                    PackageManager.GET_SIGNATURES
                )
            }
            // 获取签名（优先使用新API，兼容旧版本）
            val signatures = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                packageInfo.signingInfo?.signingCertificateHistory
            } else {
                @Suppress("DEPRECATION")
                packageInfo.signatures
            }

            if (signatures.isNullOrEmpty()) {
                Log.e(TAG, "未找到应用签名")
                return null
            }

            // 解析第一个签名为X509证书（多签名场景需遍历）
            val signature: Signature = signatures[0]
            val certFactory = CertificateFactory.getInstance("X.509")
            val x509Certificate = certFactory.generateCertificate(
                signature.toByteArray().inputStream()
            ) as X509Certificate

            // 提取公钥并转为Base64字符串（去除换行和空格）

            val publicKeyBytes = x509Certificate.publicKey.encoded
            val publicKeyBase64 = Base64.encodeToString(publicKeyBytes, Base64.NO_WRAP)

            Log.d(TAG, "提取到公钥：\n$publicKeyBase64")
            Log.d(TAG, "可直接用作LEGAL_PUBLIC_KEY的值")

            publicKeyBase64
        } catch (e: Exception) {
            Log.e(TAG, "提取公钥失败", e)
            null
        }
    }

    fun extractCN(context: Context): String? {
        return try {
            // 获取当前应用的签名信息
            val packageManager = context.packageManager

            val packageInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                // Android 9+ 使用新 API
                packageManager.getPackageInfo(
                    context.packageName,
                    PackageManager.GET_SIGNING_CERTIFICATES
                )
            } else {
                // 低版本使用旧 API
                @Suppress("DEPRECATION")
                packageManager.getPackageInfo(
                    context.packageName,
                    PackageManager.GET_SIGNATURES
                )
            }

            // 获取签名（优先使用新API，兼容旧版本）
            val signatures = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                packageInfo.signingInfo?.signingCertificateHistory
            } else {
                @Suppress("DEPRECATION")
                packageInfo.signatures
            }

            if (signatures.isNullOrEmpty()) {
                Log.e(TAG, "未找到应用签名")
                return null
            }

            // 解析第一个签名为X509证书（多签名场景需遍历）
            val signature: Signature = signatures[0]
            val certFactory = CertificateFactory.getInstance("X.509")
            val x509Certificate = certFactory.generateCertificate(
                signature.toByteArray().inputStream()
            ) as X509Certificate

            // 从X509证书中提取CN（Common Name）
            val subjectDN = x509Certificate.subjectX500Principal.name
            val cnValue = extractCNFromDN(subjectDN)

            Log.d(TAG, "提取到CN：$cnValue")
            cnValue
        } catch (e: Exception) {
            Log.e(TAG, "提取CN失败", e)
            null
        }
    }

    /**
     * 从DN（Distinguished Name）字符串中解析出CN（Common Name）
     * DN格式示例："CN=Example, O=Company, L=City, ST=State, C=Country"
     */
    private fun extractCNFromDN(dn: String): String? {
        // 分割DN的各个部分（处理可能的空格）
        val dnParts = dn.split(",").map { it.trim() }
        // 查找以"CN="开头的部分并截取值
        return dnParts.firstOrNull { it.startsWith("CN=") }?.substringAfter("CN=")
    }


    // 获取PackageInfo（避免直接用PackageManager，减少Hook风险）
    private fun getPackageInfo(context: Context): PackageInfo {

        val packageManager = context.packageManager

      return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            // Android 9+ 使用新 API
            packageManager.getPackageInfo(
                context.packageName,
                PackageManager.GET_SIGNING_CERTIFICATES
            )
        } else {
            // 低版本使用旧 API
            @Suppress("DEPRECATION")
            packageManager.getPackageInfo(
                context.packageName,
                PackageManager.GET_SIGNATURES
            )
        }
    }

    // 计算签名的SHA256哈希
    private fun getSignatureSha256(signature: Signature): String {
        val md = MessageDigest.getInstance("SHA-256")
        md.update(signature.toByteArray())
        return bytesToHex(md.digest())
    }
    private fun getCertSha256(signature: Signature): String {
        val certFactory = CertificateFactory.getInstance("X.509")
        val cert = certFactory.generateCertificate(signature.toByteArray().inputStream()) as X509Certificate
        val md = MessageDigest.getInstance("SHA-256")
        val digest = md.digest(cert.encoded)
        return digest.joinToString(":") { "%02X".format(it) } // 带冒号的格式
    }

    /**
     * 从签名中提取公钥（正确方式）
     * @return 公钥的Base64编码字符串（与LEGAL_PUBLIC_KEY格式一致）
     */
    fun getPublicKeyFromSignature(signature: Signature): String {
        val cert = getX509Certificate(signature)
        // 获取公钥的原始字节数组，再转为Base64字符串（无换行）
        val publicKeyBytes = cert.publicKey.encoded
        return Base64.encodeToString(publicKeyBytes, Base64.NO_WRAP)
    }

    /**
     * 解析签名为X509证书
     */
    private fun getX509Certificate(signature: Signature): X509Certificate {
        val certFactory = CertificateFactory.getInstance("X.509")
        return certFactory.generateCertificate(signature.toByteArray().inputStream()) as X509Certificate
    }


    // 字节数组转十六进制字符串
    private fun bytesToHex(bytes: ByteArray): String {
        val hexChars = CharArray(bytes.size * 2)
        for (i in bytes.indices) {
            val v = bytes[i].toInt() and 0xFF
            hexChars[i * 2] = "0123456789ABCDEF"[v ushr 4]
            hexChars[i * 2 + 1] = "0123456789ABCDEF"[v and 0x0F]
        }
        return String(hexChars)
    }
}